<?php

/**
 * Manages in-/output of data
 * @since  0.0.1
 *
 * Controllers are one of the three important parts of MVC. It reacts on input
 * from the user, reads and stores information from / in the Model and show
 * it to the client via View.
 *
 * They define how to read, evaluate, store and act on incoming data. An
 * instance can represent each file that's located in "/app/Controller"
 *
 *
 * @section Changelog
 *
 * <table>
 * 	<tr>
 * 		<th>Version</th>
 * 		<th>Description</th>
 *  </tr>
 *  <tr><td>0.0.9</td><td>Class-variables useable within according PHP file</td></tr>
 *  <tr><td>0.2.0</td><td>Controller::get added as alias of Controller::__get</td></tr>
 *  <tr><td>0.2.0</td><td>Controller::set added as alias of Controller::__set</td></tr>
 *  <tr><td>0.2.0</td><td>Controller::getIterator added to iterate over placeholders</td></tr>
 * </table>
 * 
 * @extends MagicTree_Abstract
 *
 *
 * @section Examples
 *
 * @subsection Controller_Instance Define and use Controller
 * Firstly we want to make a Controller that sends something to the Client and
 * another one that get's it and delivers some values
 *
 * <pre>/app/Controller/index.php</pre>
 * @code
 * <?php
 *
 * echo "Foo is: " . $foo;
 *
 * ?>
 * @endcode
 *
 * <pre>Output "/"</pre>
 * @verbatim	Foo is: @endverbatim
 *
 * <pre>/app/Controller/test/test.php</pre>
 * @code
 * <?php
 *
 * $c = new Controller('index');	// get the controller "/app/Controller/index.php"
 * $c->foo = 123;					// put some data in it
 *
 * echo $c;						// dispatch
 * ?>
 * @endcode
 * \nomagic{ Controller::set() also writes data in it:,
 *           $c->set("foo"\, 123);
 *  }
 *
 * <pre>Output "/test":</pre>
 * @verbatim	Foo is: 123 @endverbatim
 *
 * \note{	Please use a View,
 * 			To generate a correct output of your site always try to use a
 * 			View.
 * }
 * 
 * @subsection Controller-IteratePlaceholder Iterate placeholders
 * 
 * To know which placeholders are currently used, or even to transform them
 * you can use the iteratable characteristics of the Controller:
 * 
 * @code
 * <?php
 * 
 * // get a controller and set placeholders
 * $ctrl = new Controller("some_file");
 * $ctrl->some = "example"; 
 * $ctrl->foo  = "bar";
 * 
 * // iterate
 * foreach ($ctrl as $placeholder => $value)
 * {
 * 	echo "The '$placeholder' contains '$value' \n";
 * }
 * 
 * ?>
 * @endcode
 *
 * \content{ Output,
 * The 'some' contains 'example'
 * The 'foo' contains 'bar'
 * }
 * 
 * \nomagic{ Controller::getIterator also gives you the iterateable array,
 *           foreach( $ctrl->getIterator() as $placeholder => $value)
 * }
 *
 * @see Model
 * @see View
 *
 */
class Controller extends    MagicTree_Abstract
                 implements Pipeline, IteratorAggregate
{
	private   $_file = NULL,
	          $_valid = false;
	        
	protected $_map = array();


	/**
	 * Alias of Controller::__invoke()
	 *
	 * Alias of Controller::__invoke()
	 *
	 * @since 0.1.1
	 */
	public function pipe($in)
	{
		$this->__invoke($in);
	}

	/**
	 * Get a variable of the controller
	 * @todo magical include 
	 */
	public function __get($item)
	{
		if (!isset($this->_map[$item]))
		{
			return NULL;
		}
		return $this->_map[$item];
	}
	

	/**
	 * Pipe different object or array in Controller
	 *
	 * @since 0.1.1
	 *
	 * @copydoc Pipeline::__invoke()
	 *
	 * @see Pipeline::__invoke()
	 */
	public function __invoke($in)
	{
		if (is_array($in))
		{
			$this->_map = array_replace(
		               		$this->_map,
		               		$in
			);
		}
		else if ($in instanceof Iterator)
		{
			$r = "";
			foreach ($in as $set)
			{
				$r .= (string) $this->__invoke($set);
			}

			return $r;
		}

		return $this;
	}

	public function __toString()
	{
		global $site;

		$file = Registry::get("controller", "path")
		      . "/" . $this->_file . ".php";

		if (file_exists($file))
		{
			ob_start();
			extract($this->_map, EXTR_OVERWRITE & EXTR_REFS);
			include $file;
			return ob_get_clean();
		}
		else
		{
			$view = new View($this->_file);
			return (string) $view($this->_map);
		}
	}
	
	/**
	 * Get a variable of the Controller
	 * 
	 * @since 0.2.0
	 * 
	 * @param string $variable Name of the variable
	 * 
	 * @return \c object Value of this variable
	 * 
	 * @see Controller::__get
	 * @see MagicTree_Abstract::get
	 */
	public function get($variable)
	{
		return $this->__get($variable);
	}
	
	/**
	 * Makes Controller iterateable
	 * 
	 * To know which values are within the Controller you can use it
	 * almost like an array known from PHP.
	 * 
	 * @since 0.2.0
	 * 
	 * @return \c ArrayIterator Array of the placeholders and values
	 * 
	 * @section Controller-getIterator_Examples Examples
	 * 
	 * @subsection Controller-getIterator_Foreach Foreach over a Controller
	 * @code
	 * <?php
	 * 
	 * $ctrl = new Controller("some_controller");
	 * $ctrl->foo = "bar";
	 * 
	 * foreach ($ctrl->getIterator() as $placeholder => $value)
	 * {
	 * 	echo "The variable '$placeholder' will be '$value' \n";
	 * }
	 * 
	 * ?>
	 * @endcode
	 * \content{ Output,
	 * The variable 'foo' will be 'var'
	 * }
	 * 
	 * \magic{ PHP uses this method internal so you can shorten it,
	 *         foreach ( $ctrl as $placeholder => $value )
	 * }
	 * 
	 * @see Controller::__get
	 * @see Controller::__set
	 */
	public function getIterator()
	{
		return new ArrayIterator($this->_map);
	}
	
	/**
	 * @copybrief Controller::__set()
	 * 
	 * Alias of Controller::__set()
	 * 
	 * @since 0.2.0
	 * 
	 * @param string $variable Name of the variable to change
	 * @param object $value    Value of this variable
	 * 
	 * @see Controller::__set
	 */
	public function set($variable, $value)
	{
		return $this->__set($variable, $value);
	}
	
	public function __construct($file = NULL)
	{
		if ($file === NULL)
		{
			$this->_file = DIR . FILE;
		}
		else
		{
			$this->_file = $file;
		}

		$append = Registry::get("controller/append");

		if (is_array($append))
		foreach ($append as $s)
		{
			if (   $s != ""
			    && file_exists("app/Controller/" . $this->_file . $s . ".php")
			    )
			{
				$this->_file .= $s;
			}
		}
	}
}